home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1999 Spring / macformat-077.iso / Shareware Plus / Development / Akua Sweets 131 / Akua Sweets Examples / Network / PowerSPrint 142 / PowerSPrint Server < prev   
Encoding:
Text File  |  1999-03-04  |  18.5 KB  |  832 lines  |  [TEXT/ToyS]

  1. (*
  2. V1.42 ◊ This script is © 1998-1999 by AKUA interactive media AG.
  3.  
  4. See the included documentation for more information.
  5.  
  6. V142/26Feb99/Update to Akua Sweets V1.31 (creator 'AkuS'), fix removed orphan problem
  7. V141/07Feb99/Fix "Touched of 0" error
  8. V140/02Feb99/Fix some prefs stuff, fix size fork error in Akua Sweets
  9. V130/22Jan99/Lots 'o Fixes - add return of printer configuration to prefs check
  10. V120/10Jan99/Pass back Epson Settings to clients
  11. V110/04Jan99/Redid a lot of stuff. Fixed a lot of bugs
  12. V102/25Jul98/Work on timing to avoid Quadra Crash of AppleScript
  13. V101/11Jul98/Better check of "initted" status, Quit when inactive, Better trashing of orphaned files.
  14. *)
  15.  
  16. -- User setable properties
  17. property kasAllowAlerts : true -- Set to false to stop any alerts from appearing
  18. property kcnTimeOut : 300 -- Kill operations if not touched in this many seconds
  19. property kasStayOpen : true -- Stay open all the time to avoid startup delays
  20.  
  21. -- Internal Properties
  22. property kasFinder : "Finder" -- The Finder
  23. property kpsTitle : "PowerSPrint Server"
  24. property kpsVersion : "V1.42"
  25. property kpsTitleW : kpsTitle & " " & kpsVersion
  26. property kpfPrefName : kpsTitle & " V1.3" -- Prefs version
  27.  
  28. -- Internal Globals
  29. property gasReady : false
  30.  
  31. global gdvPrefs -- (Epson) Driver Files & Dates
  32.  
  33. global gpsStatus -- Window with status info
  34. global gpsStatLoc -- Location of status window
  35. global gpsSpool -- Spool folder
  36. global gpsSpooled -- Number of items in Spool folder
  37. global gpsSpoolTypes -- Types of files stored in spool folder that our ours
  38. global gpsWantLaunch -- Launch real print monitor?
  39. global gpsPosted -- List of files to post process
  40.  
  41. global gpsMonitor -- Alias of our PrintMonitor
  42. global gpsMonCre -- Creator of our PrintMonitor
  43.  
  44. global gcnFidBase -- Base file id
  45. global gcnCopySlot -- List of copy slots
  46. global gcnBatchSlot -- List of batch slots
  47. global gcnWaitingFor -- # of Files we are awaiting
  48.  
  49. global gasInitted -- Just a holder to see if we've been initted
  50. global gasLastTouch -- Last time touched
  51.  
  52.  
  53. on run
  54.     set gasReady to false
  55.     init()
  56.     spCheckLamers()
  57.     return false
  58. end run
  59.  
  60.  
  61. on init()
  62.     if ((the open windows) is {}) then -- No status window?
  63.         set gasReady to false
  64.         set gpsWantLaunch to false
  65.         set gpsSpooled to 0
  66.         set gcnWaitingFor to 0
  67.         set gcnCopySlot to {}
  68.         set gcnBatchSlot to {}
  69.         set gpsPosted to {}
  70.         set gcnFidBase to (pause for 0)
  71.         set gasLastTouch to the clock in offset form
  72.         set gdvPrefs to 0
  73.         pfLoad()
  74.         StatusNew()
  75.     end if
  76. end init
  77.  
  78.  
  79. on idle
  80.     init()
  81.     
  82.     if (not spSetup()) then
  83.         Status("Waiting for Setup…")
  84.         return 3
  85.     end if
  86.     
  87.     Status("Thinking…")
  88.     dvCheckPrefs()
  89.     cnCheckOrphans()
  90.     StatusUpdate()
  91.     
  92.     if (gcnWaitingFor is 0) then
  93.         if (gpsSpooled > 0) then
  94.             set gasLastTouch to the clock in offset form
  95.             pmLaunch()
  96.         else
  97.             pmQuit()
  98.         end if
  99.         Status("Idle.")
  100.     else
  101.         if ((the clock in offset form) - gasLastTouch) > 120 then set gcnWaitingFor to 0 -- Lost clients?
  102.         Status("Receiving " & gcnWaitingFor & " files.")
  103.     end if
  104.     
  105.     if (gpsWantLaunch) then
  106.         pmLaunch()
  107.         set gpsWantLaunch to false
  108.     end if
  109.     
  110.     if not kasStayOpen then ¬
  111.         if ((the clock in offset form) - gasLastTouch) > 600 then quit
  112.     
  113.     set gasReady to true
  114.     
  115.     return 15
  116. end idle
  117.  
  118.  
  119. on CheckReady()
  120.     return gasReady
  121. end CheckReady
  122.  
  123.  
  124. on quit
  125.     set gasReady to false
  126.     try
  127.         StatusDel()
  128.         pfSave()
  129.     on error
  130.         beep
  131.     end try
  132.     continue quit
  133. end quit
  134.  
  135.  
  136. on open fsObjs
  137.     init()
  138.     
  139.     repeat with fsObj in fsObjs
  140.         set fInfo to basic info for fsObj
  141.         
  142.         if (catalog kind of fInfo) is a folder then
  143.             spSet(fsObj)
  144.         else if (system type of fInfo) is "APPL" then
  145.             pmSet(fsObj)
  146.         else
  147.             ShowErr("Not ready!")
  148.         end if
  149.     end repeat
  150. end open
  151.  
  152.  
  153. on pfLoad()
  154.     try
  155.         set prefs to load preference named kpfPrefName
  156.     on error
  157.         -- Default values
  158.         set prefs to ¬
  159.             {PfStatLoc:{44, 64} ¬
  160.                 , PfMonitor:0 ¬
  161.                 , PfMonCre:("") ¬
  162.                 , PfSpool:path to printmonitor ¬
  163.                 , PfSpoolTypes:{} ¬
  164.                 }
  165.     end try
  166.     
  167.     -- Set globals from prefs
  168.     set gpsStatLoc to PfStatLoc of prefs
  169.     set gpsMonitor to PfMonitor of prefs
  170.     set gpsMonCre to PfMonCre of prefs
  171.     set gpsSpool to PfSpool of prefs
  172.     set gpsSpoolTypes to PfSpoolTypes of prefs
  173. end pfLoad
  174.  
  175.  
  176. on pfSave()
  177.     if (gpsStatus is not 0) then
  178.         set newLoc to screen location of ¬
  179.             (display info gpsStatus message "Saving prefs…" at line 2)
  180.         if (not (the same data is in newLoc as in gpsStatLoc)) then ¬
  181.             set gpsStatLoc to newLoc
  182.     end if
  183.     
  184.     -- Appending {} to the end of this causes crashes in System 7.x
  185.     set prefs to ¬
  186.         {PfStatLoc:gpsStatLoc ¬
  187.             , PfMonitor:gpsMonitor ¬
  188.             , PfMonCre:gpsMonCre ¬
  189.             , PfSpool:gpsSpool ¬
  190.             , PfSpoolTypes:gpsSpoolTypes ¬
  191.             }
  192.     
  193.     save preference prefs named kpfPrefName
  194. end pfSave
  195.  
  196.  
  197. on dvCheckPrefs()
  198.     if (gdvPrefs is 0) then
  199.         ShowAction("Scanning driver prefs…")
  200.         set gdvPrefs to {}
  201.         
  202.         try
  203.             set epf to (((path to preferences folder) as string) & "Epson Preferences") as alias
  204.         on error
  205.             ShowAction("…")
  206.             return
  207.         end try
  208.         
  209.         set pfs to the entries in epf whose types are in {"pref"}
  210.         
  211.         repeat with pf in pfs
  212.             set pff to (epf as string) & pf
  213.             set gcnt to the number of resources in pff ¬
  214.                 of type "Gest"
  215.             if gcnt > 0 then ¬
  216.                 set gdvPrefs to gdvPrefs & {basic info for pff}
  217.         end repeat
  218.         ShowAction("…")
  219.     end if
  220. end dvCheckPrefs
  221.  
  222.  
  223. on dvReturnFile(binfo)
  224.     -- Return the contents of a driver pref file
  225.     try
  226.         set epf to (((path to preferences folder) as string) & "Epson Preferences") as alias
  227.         set fsObj to (epf as string) & (catalog name of binfo)
  228.     on error
  229.         beep
  230.         return
  231.     end try
  232.     
  233.     try
  234.         set df to read data from the data fork of fsObj
  235.     on error
  236.         set df to 0
  237.     end try
  238.     
  239.     try
  240.         set fk to open fork from fsObj ¬
  241.             with resource fork
  242.         set rf to read data from fk
  243.         close fork fk
  244.     on error
  245.         set rf to 0
  246.     end try
  247.     
  248.     return {df, rf}
  249. end dvReturnFile
  250.  
  251.  
  252. on pmLaunch()
  253.     if (gpsMonCre is not "") then
  254.         if (all processes given «class Creå»:gpsMonCre) is {} then
  255.             Status("Launching Print Monitor")
  256.             try
  257.                 arouse gpsMonitor
  258.             on error
  259.                 ShowErr("Couldn't launch Monitor!")
  260.             end try
  261.         else
  262.             Status("Print Monitor is up.")
  263.         end if
  264.     else
  265.         Status("Error - No Print Monitor!")
  266.     end if
  267. end pmLaunch
  268.  
  269.  
  270. on pmQuit()
  271.     if (gpsMonCre is not "") and ¬
  272.         (all processes given «class Creå»:gpsMonCre) is not {} then
  273.         Status("Quitting Print Monitor")
  274.         tell application (original name of (alias info from gpsMonitor)) to quit
  275.     end if
  276. end pmQuit
  277.  
  278.  
  279. on pmSet(fsObj)
  280.     set gpsMonitor to fsObj
  281.     set gpsMonCre to system creator of (basic info for fsObj)
  282.     pfSave()
  283.     pmShow()
  284. end pmSet
  285.  
  286.  
  287. on pmShow()
  288.     display info gpsStatus ¬
  289.         message ("Monitor: " & (gpsMonitor as string)) ¬
  290.         at line 10 ¬
  291.         using color 16
  292. end pmShow
  293.  
  294.  
  295. on spSet(fsObj)
  296.     set gpsSpool to fsObj
  297.     pfSave()
  298.     spShow()
  299. end spSet
  300.  
  301.  
  302. on spShow()
  303.     display info gpsStatus ¬
  304.         message ("Spool: " & (gpsSpool as string)) ¬
  305.         at line 9 ¬
  306.         using color 17
  307. end spShow
  308.  
  309.  
  310. on spNameFile(fname, tag)
  311.     if (tag is not "") then
  312.         if (character 2 of tag is "1") then
  313.             set fname to tag & fname
  314.         else
  315.             set fname to replace data in fname ¬
  316.                 starting after position 0 ¬
  317.                 with contents of tag
  318.         end if
  319.     end if
  320.     
  321.     return fname
  322. end spNameFile
  323.  
  324.  
  325. on spCheckName(fname, tag)
  326.     set fname to spNameFile(fname, tag)
  327.     
  328.     repeat while (the entries in gpsSpool whose names match fname) is not {}
  329.         if (character 1 of fname is "◊") then
  330.             set n to (the text 2 thru 5 of fname) as number
  331.             set n to n + 1
  332.             set tag to "◊" & (n as string)
  333.             set fname to replace data in fname ¬
  334.                 starting after position 0 ¬
  335.                 with contents of tag
  336.         else
  337.             if (length of fname < 15) then
  338.                 set tag to "◊1000 "
  339.                 set fname to tag & fname
  340.             else
  341.                 set tag to "◊2000 "
  342.                 set fname to replace data in fname ¬
  343.                     starting after position 0 ¬
  344.                     with contents of tag
  345.             end if
  346.         end if
  347.     end repeat
  348.     
  349.     return tag
  350. end spCheckName
  351.  
  352.  
  353. on spCount()
  354.     if (gpsMonCre is {}) then return 0
  355.     return the number of items in ¬
  356.         (the entries in gpsSpool whose creators are in {gpsMonCre})
  357. end spCount
  358.  
  359.  
  360. on spCheckLamers()
  361.     set orphs to (the entries in gpsSpool whose creators are in {"AkuS"})
  362.     set daddy to (gpsSpool as string)
  363.     
  364.     repeat with orph in orphs
  365.         collate ((daddy & orph) as alias) with the deleter
  366.     end repeat
  367. end spCheckLamers
  368.  
  369.  
  370. on spSetup()
  371.     if (CheckReady()) then return true
  372.     
  373.     if (gpsStatus is not 0) then
  374.         spShow()
  375.         
  376.         if (control key down of (input state)) then
  377.             try
  378.                 open {choose file with prompt "Choose the Print Monitor" of type {"APPL"}}
  379.             on error
  380.                 beep
  381.             end try
  382.         end if
  383.         
  384.         if (shift key down of (input state)) then
  385.             try
  386.                 open {choose folder with prompt "Choose Spool Folder (e.g. Spool Folder5)"}
  387.             on error
  388.                 beep
  389.             end try
  390.         end if
  391.         
  392.         if (gpsMonitor is 0) then
  393.             display info gpsStatus ¬
  394.                 message ("Control Key = Choose Print Monitor") ¬
  395.                 at line 3 ¬
  396.                 using color (16 * 1024)
  397.             display info gpsStatus ¬
  398.                 message ("Shift Key = Choose Spool Folder") ¬
  399.                 at line 4 ¬
  400.                 using color (15 * 1024)
  401.             return false
  402.         end if
  403.         
  404.         pmShow()
  405.         
  406.         display info gpsStatus ¬
  407.             message ("Ready.") ¬
  408.             at line 3 ¬
  409.             using color (16 * 32)
  410.         display info gpsStatus ¬
  411.             message ("…") ¬
  412.             at line 4 ¬
  413.             using color (15 * 32)
  414.     end if
  415.     
  416.     return true
  417. end spSetup
  418.  
  419.  
  420. on StatusNew()
  421.     set gpsStatus to ¬
  422.         display info titled kpsTitleW ¬
  423.             message ("Starting up…") ¬
  424.             located at gpsStatLoc
  425. end StatusNew
  426.  
  427.  
  428. on StatusUpdate()
  429.     if (gpsStatus is not 0) then
  430.         set gpsSpooled to spCount()
  431.         
  432.         set newLoc to screen location of ¬
  433.             (display info gpsStatus ¬
  434.                 message ("Spooled Files: " & gpsSpooled))
  435.         if (not (the same data is in newLoc as in gpsStatLoc)) then
  436.             set gpsStatLoc to newLoc
  437.             pfSave()
  438.         end if
  439.     end if
  440. end StatusUpdate
  441.  
  442.  
  443. on Status(msg)
  444.     if (gpsStatus is not 0) then
  445.         display info gpsStatus ¬
  446.             message msg ¬
  447.             at line 2
  448.     end if
  449. end Status
  450.  
  451.  
  452. on ShowAction(msg)
  453.     if (gpsStatus is not 0) then
  454.         display info gpsStatus ¬
  455.             message msg ¬
  456.             at line 3
  457.     end if
  458. end ShowAction
  459.  
  460.  
  461. on ShowErr(msg)
  462.     if (gpsStatus is not 0) then
  463.         set msg to "Err " & (the clock using form "%d-%h:%i:%s") & ": " & msg
  464.         display info gpsStatus ¬
  465.             message msg at line 8 ¬
  466.             using bg color (30 * 1024) + (20 * 32) + 20
  467.         if (last character of msg is "!") then beep
  468.         pause for 300
  469.     end if
  470. end ShowErr
  471.  
  472.  
  473. on StatusDel()
  474.     set newLoc to screen location of ¬
  475.         (display info gpsStatus with disposal)
  476.     if (not (the same data is in newLoc as in gpsStatLoc)) then ¬
  477.         set gpsStatLoc to newLoc
  478.     set gpsStatus to 0
  479. end StatusDel
  480.  
  481.  
  482. on ClientReg()
  483.     return {SrvrVersion:kpsVersion, SrvrApp:(resolve chain (path to me)), SrvrDrvrPrefs:gdvPrefs, SrvrSetup:printer configuration}
  484. end ClientReg
  485.  
  486.  
  487. on ClientInq()
  488. end ClientInq
  489.  
  490.  
  491. on cnBatchTouched(bn)
  492.     set t to 0
  493.     
  494.     repeat with cs in gcnCopySlot
  495.         if (not (the same data is in cs as in 0)) then
  496.             if (the same data is in (rcBatchID of cs) as in bn) and ((rcTouched of cs) > t) then ¬
  497.                 set t to (rcTouched of cs)
  498.         end if
  499.     end repeat
  500.     
  501.     return t
  502. end cnBatchTouched
  503.  
  504.  
  505. on cnCheckOrphans()
  506.     set n to the number of items of gcnCopySlot
  507.     set nt to the clock in offset form
  508.     
  509.     repeat with i from 1 to n
  510.         if (not (the same data is in (item i of gcnCopySlot) as in 0)) then
  511.             copy rcBatchID of (item i of gcnCopySlot) to bn
  512.             if (bn is 0) then
  513.                 set tt to rcTouched of (item i of gcnCopySlot)
  514.             else
  515.                 set tt to cnBatchTouched(bn)
  516.             end if
  517.             if (nt - tt) > kcnTimeOut then ¬
  518.                 CopyEnd(i + gcnFidBase, 911)
  519.         end if
  520.     end repeat
  521.     
  522.     set n to the number of items of gpsPosted
  523.     
  524.     repeat with i from 1 to n
  525.         copy item i of gpsPosted to po
  526.         if (po is not 0) then
  527.             -- Timed out?
  528.             set bn to rcBatchID of po
  529.             if (bn is 0) then
  530.                 set tt to (rcTouch of po)
  531.             else
  532.                 set tt to cnBatchTouched(bn)
  533.             end if
  534.             if (nt - tt) > 900 then
  535.                 set orphan to (rcFile of po)
  536.                 try
  537.                     set oinfo to (basic info for orphan)
  538.                     -- Make sure it wasn't overwritten by a retry…
  539.                     if (system type of oinfo is "Part") then ¬
  540.                         collate orphan with the deleter
  541.                     ShowErr("Removed completed orphan (" & nt & ", " & tt & ", " & bn & ")")
  542.                 on error
  543.                     ShowErr("Can't remove orphan!")
  544.                 end try
  545.                 set item i of gpsPosted to 0
  546.             end if
  547.         end if
  548.     end repeat
  549. end cnCheckOrphans
  550.  
  551.  
  552. on CopyPrep(cname, fNameList)
  553.     init()
  554.     
  555.     set fileCnt to (number of items in fNameList)
  556.     ShowAction(fileCnt & " file(s) from " & cname)
  557.     set gcnWaitingFor to gcnWaitingFor + fileCnt
  558.     
  559.     set tag to ""
  560.     repeat with fname in fNameList
  561.         set tag to spCheckName(fname, tag)
  562.     end repeat
  563.     
  564.     set cnt to (the number of items of gcnBatchSlot)
  565.     set bid to cnt
  566.     repeat with i from 1 to cnt
  567.         if (item i of gcnBatchSlot) is 0 then
  568.             set bid to i - 1
  569.             exit repeat
  570.         end if
  571.     end repeat
  572.     set bid to bid + 1
  573.     
  574.     set cs to {rcBatchID:bid, rcBatchFiles:fileCnt, rcBatchTag:tag}
  575.     
  576.     if bid ≤ cnt then
  577.         set item bid of gcnBatchSlot to cs
  578.     else
  579.         set gcnBatchSlot to gcnBatchSlot & {cs}
  580.     end if
  581.     
  582.     repeat with fname in fNameList
  583.         set newName to spNameFile(fname, tag)
  584.         -- write data to the data fork of ((gpsSpool as string) & newName) from buffer "Akua"
  585.     end repeat
  586.     
  587.     set gasLastTouch to the clock in offset form
  588.     return bid + gcnFidBase
  589. end CopyPrep
  590.  
  591.  
  592. on CopyBeg(cname, prepNumOrZero, fInfo)
  593.     init()
  594.     if (gpsSpool is 0) then return -1
  595.     
  596.     ShowAction("Copy from " & cname & ", batch: " & prepNumOrZero)
  597.     
  598.     set tag to ""
  599.     if (prepNumOrZero is not 0) then ¬
  600.         set tag to rcBatchTag of (item (prepNumOrZero - gcnFidBase) of gcnBatchSlot)
  601.     set catalog name of fInfo to spNameFile(catalog name of fInfo, tag)
  602.     
  603.     set fid to (the number of items of gcnCopySlot)
  604.     repeat with i from 1 to fid
  605.         if (item i of gcnCopySlot) is 0 then
  606.             set fid to i - 1
  607.             exit repeat
  608.         end if
  609.     end repeat
  610.     set fid to fid + 1
  611.     
  612.     ShowAction("Copy id " & fid)
  613.     
  614.     set dRef to 0
  615.     set rRef to 0
  616.     
  617.     -- Make sure we create the file if it is 0 total long
  618.     if ((data fork length of fInfo) > 0) or ((resource fork length of fInfo) is 0) then
  619.         set dRef to open fork from gpsSpool ¬
  620.             named (catalog name of fInfo) ¬
  621.             of type ("Part") ¬
  622.             of creator ("AkuS") ¬
  623.             with write access
  624.         size fork dRef to (data fork length of fInfo) with reservation
  625.     end if
  626.     
  627.     if (resource fork length of fInfo) > 0 then
  628.         set rRef to open fork from gpsSpool ¬
  629.             named (catalog name of fInfo) ¬
  630.             of type ("Part") ¬
  631.             of creator ("AkuS") ¬
  632.             with resource fork and write access
  633.         size fork rRef to (resource fork length of fInfo) with reservation
  634.     end if
  635.     
  636.     set dstAli to ((gpsSpool as string) & (catalog name of fInfo)) as alias
  637.     set nowT to the clock in offset form
  638.     
  639.     set pg to display progress titled (cname & " (" & fid & ")") ¬
  640.         subtitled (catalog name of fInfo) ¬
  641.         maximum ((resource fork length of fInfo) + (data fork length of fInfo)) ¬
  642.         located at {-1, -1} ¬
  643.         labeled "Starting…"
  644.     
  645.     set cs to {rcClientName:cname ¬
  646.         , rcBatchID:prepNumOrZero ¬
  647.         , rcProgWind:pg ¬
  648.         , rcBirthed:nowT ¬
  649.         , rcTouched:nowT ¬
  650.         , rcInfo:fInfo ¬
  651.         , rcDestFile:dstAli ¬
  652.         , rcDoingRsrc:false ¬
  653.         , rcDataRef:dRef ¬
  654.         , rcDataOff:0 ¬
  655.         , rcRsrcRef:rRef ¬
  656.         , rcRsrcOff:0}
  657.     
  658.     if fid ≤ (number of items of gcnCopySlot) then
  659.         set item fid of gcnCopySlot to cs
  660.     else
  661.         set gcnCopySlot to gcnCopySlot & {cs}
  662.     end if
  663.     
  664.     return fid + gcnFidBase
  665. end CopyBeg
  666.  
  667.  
  668. on CopyFork(fid, isRsrc)
  669.     set fid to fid - gcnFidBase
  670.     copy item fid of gcnCopySlot to cs
  671.     
  672.     if (the same data is in cs as in 0) then
  673.         ShowErr("Error finding Fid in CF: " & fid & "!")
  674.         return 912 -- timeout
  675.     end if
  676.     
  677.     ShowAction("Copy Fork: " & catalog name of (rcInfo of cs))
  678.     
  679.     if (isRsrc) then
  680.         set lbl to "Resource Fork"
  681.     else
  682.         set lbl to "Data Fork"
  683.     end if
  684.     
  685.     set rcDoingRsrc of cs to isRsrc
  686.     
  687.     display progress (rcProgWind of cs) ¬
  688.         labeled lbl
  689.     
  690.     set rcTouched of cs to the clock in offset form
  691.     set item fid of gcnCopySlot to cs
  692.     return 0
  693. end CopyFork
  694.  
  695.  
  696. on CopyChunk(fid, isRsrc, buf, dataOffset)
  697.     set fid to fid - gcnFidBase
  698.     set cs to item fid of gcnCopySlot
  699.     
  700.     if (the same data is in cs as in 0) then
  701.         ShowErr("Error finding Fid in CC: " & fid & "!")
  702.         return 913 -- timeout
  703.     end if
  704.     
  705.     ShowAction("Copy Chunk: " & catalog name of (rcInfo of cs))
  706.     
  707.     set cnt to the data length of buf
  708.     
  709.     if (isRsrc) then
  710.         set fRef to rcRsrcRef of cs
  711.         copy rcRsrcOff of cs to fOff
  712.         set rcRsrcOff of cs to (fOff + cnt)
  713.     else
  714.         set fRef to rcDataRef of cs
  715.         copy rcDataOff of cs to fOff
  716.         set rcDataOff of cs to (fOff + cnt)
  717.     end if
  718.     
  719.     if (dataOffset is not fOff) then ¬
  720.         return CopyEnd(fid, -50)
  721.     
  722.     write data to fRef ¬
  723.         from buffer buf ¬
  724.         at offset fOff
  725.     
  726.     display progress (rcProgWind of cs) ¬
  727.         value ((rcRsrcOff of cs) + (rcDataOff of cs))
  728.     
  729.     set gasLastTouch to the clock in offset form
  730.     set rcTouched of cs to gasLastTouch
  731.     set item fid of gcnCopySlot to cs
  732.     return 0
  733. end CopyChunk
  734.  
  735.  
  736. on CopyEnd(fid, errNum)
  737.     set fid to fid - gcnFidBase
  738.     
  739.     set gcnWaitingFor to gcnWaitingFor - 1
  740.     
  741.     copy item fid of gcnCopySlot to cs
  742.     set item fid of gcnCopySlot to 0
  743.     
  744.     if (cs is 0) then
  745.         ShowErr("Error finding Fid in CE: " & fid & "!")
  746.         return 914 -- timeout
  747.     end if
  748.     
  749.     ShowAction("Copy Finish: " & catalog name of (rcInfo of cs))
  750.     
  751.     set pg to rcProgWind of cs
  752.     if (pg is not 0) then display progress pg labeled "Finishing…"
  753.     
  754.     set dRef to rcDataRef of cs
  755.     set rRef to rcRsrcRef of cs
  756.     if (dRef is not 0) then close fork dRef
  757.     if (rRef is not 0) then close fork rRef
  758.     
  759.     if (errNum is not 0) then
  760.         ShowAction("Copy Finish: " & catalog name of (rcInfo of cs) & " ERR:" & errNum)
  761.         collate (rcDestFile of cs) with the deleter
  762.         if (pg is not 0) then display progress pg with disposal
  763.         return errNum
  764.     end if
  765.     
  766.     if (gpsSpoolTypes does not contain (system type of (rcInfo of cs))) then
  767.         set gpsSpoolTypes to gpsSpoolTypes & (system type of (rcInfo of cs))
  768.         pfSave()
  769.     end if
  770.     
  771.     if (pg is not 0) then display progress pg with disposal
  772.     
  773.     set gpsWantLaunch to (gcnWaitingFor is 0)
  774.     CopyPost(rcBatchID of cs, rcDestFile of cs, rcInfo of cs)
  775.     
  776.     ShowAction("Copied.")
  777.     
  778.     return 0
  779. end CopyEnd
  780.  
  781.  
  782. on CopyDone(batchNum)
  783.     -- Called from client to show that a batch has completed
  784.     -- … see CopyPrep to start a batch
  785.     set foundSome to false
  786.     
  787.     set n to the number of items in gpsPosted
  788.     
  789.     repeat with i from 1 to n
  790.         copy item i of gpsPosted to po
  791.         if (po is not 0) then
  792.             if the same data is in (rcBatchID of po) as in batchNum then
  793.                 try
  794.                     set the catalog info of (rcFile of po) to (rcInfo of po)
  795.                 on error errStr number errNum
  796.                     ShowErr("File System Error: " & errNum & "!")
  797.                 end try
  798.                 set item i of gpsPosted to 0
  799.                 set foundSome to true
  800.             end if
  801.         end if
  802.     end repeat
  803.     return foundSome
  804. end CopyDone
  805.  
  806.  
  807. on CopyPost(prepNum, fsObj, fsInfo)
  808.     -- Post a "file info setting" for processing after the batch completes (CopyDone)
  809.     -- … or do it now if prepNum (batchID) is 0
  810.     if (prepNum is 0) then
  811.         set the catalog info of fsObj to fsInfo
  812.     else
  813.         set newObj to {rcBatchID:prepNum ¬
  814.             , rcFile:fsObj ¬
  815.             , rcInfo:fsInfo ¬
  816.             , rcTouch:the clock in offset form}
  817.         
  818.         set n to the number of items in gpsPosted
  819.         repeat with i from 1 to n
  820.             copy item i of gpsPosted to po
  821.             if (po is 0) then
  822.                 set item i of gpsPosted to newObj
  823.                 return
  824.             end if
  825.         end repeat
  826.         
  827.         set gpsPosted to gpsPosted & {newObj}
  828.     end if
  829. end CopyPost
  830.  
  831.  
  832.